#coding:utf8

'''
File: mbg2csb.py
Author: 张宇飞
Description: 用来将CrazyStorm的弹幕文件转化成解析用的数据文件
Date: 2014-07-28
'''

import struct
############| 配置 |############
BODY_SELF  = -99998	#自身
AUTO_SELF  = -99999	#自机
ASSIGN_POS = -100000	#指定坐标
#几种内置对象类型
EMITTER         = 0
LASER           = 1
INTER_OBJ_NUM   = 2 #被支持的内置对象个数
INTER_OBJ_LIMIT = 5 #内置对象的总个数
#几种条件定义
CON_BIG_THAN = 0x0
CON_EQUAL = 0x1
CON_LESS_THAN = 0x2

CON_SIGN_TRUE = 0x0
CON_AND = 0x1
CON_OR = 0x2

CON_TO = ':' #变化到
CON_ADD = '+' #增加
CON_SUB = '-' #减少

CON_ME_DRATIO = 'D' #正比
CON_ME_FIXED = 'F' #固定
CON_ME_SIN = 'S' #正弦

#目标字节序
TARGET_BYTE_ORDER = '<'

############| 用于组织文件格式的数据类 |############

def bool_str(s):
	return 'True' == s

def nfind(s, c, n):
	'''查找ｓ中c的第ｎ次出现位置'''
	try:
		b = 0
		for k in xrange(0, n):
			b = s.find(c,b)
			if -1 == b:
				return -1
			b += 1
		return b
	except:
		return -1

def emLaMaActionDivider(data, conmap, resmap):
	''' 将一串数据分割成可以给发射器激光和遮罩使用的事件 '''
	#事件组是用&分割的,；用来分割事件(NOTE:遮罩，发射器，激光的事件是一样的可以用一个通用方法处理)
	if not data:
		return []
	ret = []
	tmp = data.split("&")
	tmp.pop()
	trendmap = {"变化到":CON_TO, "增加":CON_ADD, "减少":CON_SUB}
	methodmap = {"固定":CON_ME_FIXED, "正弦":CON_ME_SIN, "正比":CON_ME_DRATIO}
	logicsign = (('>', CON_BIG_THAN), ('<', CON_LESS_THAN), ('=', CON_EQUAL))
	for k in tmp:
		s = nfind(k, '|', 3)
		head = k[:s].split('|')
		head.pop()
		tail = k[s:].split(';')
		tail.pop()
		if not tail:
			continue
		a = {'interval':int(head[1]), 's':int(head[2]), 'ac':[]}
		for tk in tail:
			ac1 = tk.split("：")
			newmap = {'cond':[]}
			#判定条件的或且
			two = ac1[0].split('或')
			if len(two) > 1:
				#或分割的
				newmap['ncon']=CON_OR
			else:
				two = ac1[0].split('且')
				if len(two) > 1:
					#且分割的
					newmap['ncon']=CON_AND
				else:
					newmap['ncon']=CON_SIGN_TRUE
			#对每个条件取得量，逻辑运算符，值
			for o in two:
				for sign in logicsign:
					one = o.split(sign[0])
					if len(one) == 2:
						newmap['cond'].append({'which':conmap[one[0]],'sign':sign[1], 'num':float(one[1])})
						break
			#result的特殊处理	
			three = ac1[1].split("，")
			if len(three) == 1:
				#应该交给对应的类处理
				newmap['result'] = ac1[1]
			else:
				#对结果进行分解运算
				newmap['result'] = {'method':methodmap[three[1]]}
				frame = three[2].split("帧")
				#变化需要的时间
				newmap['result']['changetime'] = int(frame[0])
				#变化次数(0表示永远)
				if not frame[1]:
					newmap['result']['ntimes'] = 0
				else:
					newmap['result']['ntimes'] = int(frame[1][1:len(frame[1])-1])
				#结果描述
				for sign in trendmap:
					two = three[0].split(sign)
					if len(two) == 2:
						newmap['result']['which'] = resmap[two[0]]
						newmap['result']['sign'] = trendmap[sign]
                                                if '自机' == two[1]:
                                                    newmap['result']['num'] = AUTO_SELF
                                                else:
                                                    newmap['result']['num'] = float(two[1])
						break
			a['ac'].append(newmap)
		ret.append(a)
	return ret

class CSObj(object):
	'''内置元素, 接口类'''
	UNUSEFUL_ID = -1
	def __init__(self, tp, oridata):
		super(CSObj, self).__init__()
		self.t = tp
		self.analyze(oridata.split(','))

	def analyze(self, data):
		pass

	def data(self):
		return None

def action2data(paction):
	"""将paction转化成C结构二进制的字流"""
	ret = ''
	for k in paction:
		#3I事件间隔,间隔增量,事件个数
		ret += struct.pack("%c3I" % TARGET_BYTE_ORDER, k['interval'], k['s'], len(k['ac']))
		for ack in k['ac']:
			if len(ack['cond']) == 1:
				#一个的时候需要加上一个永真
				tAs = ack['cond'][0]['which'] | (0 << 8) | (ack['cond'][0]['sign'] << 16) | \
					(CON_EQUAL << 18) | (ack['ncon'] << 20)
				ret += struct.pack("%ci2f" % TARGET_BYTE_ORDER,  tAs, ack['cond'][0]['num'], 0)
			else:
				tAs = ack['cond'][0]['which'] | (ack['cond'][1]['which'] << 8) | (ack['cond'][0]['sign'] << 16) | \
					(ack['cond'][1]['sign'] << 18) | (ack['ncon'] << 20)
				ret += struct.pack("%ci2f" % TARGET_BYTE_ORDER, tAs,ack['cond'][0]['num'],ack['cond'][1]['num'])
			#bc?i2I 
			res = ack['result']
			if res['which'] < 0:
				#特别处理这个事件结果
				ret += struct.pack("%cb2c?f2I" % TARGET_BYTE_ORDER, res['which'], CON_TO, CON_ME_FIXED, 
						False, 0, 0, 0)
			else:
				ret += struct.pack("%cb2c?f2I" % TARGET_BYTE_ORDER, res['which'], res['sign'], res['method'], 
						0 == res['ntimes'], res['num'], res['changetime'],
						res['ntimes'])
	return ret


class Emitter(CSObj):
	"""发射器的类"""
	# 发射器的事件编号
	emconname = ("当前帧", "X坐标", "Y坐标", "半径", "半径方向",
			"条数", "周期", "角度", "范围", "宽比", 
			"高比", "不透明度", "朝向")
	# 变化的结果
	emresname = ("X坐标", "Y坐标", "半径", "半径方向", "条数", "周期",
			"角度", "范围", "速度", "速度方向", "加速度",
			"加速度方向", "生命", "类型", "宽比", "高比", 
			"R", "G", "B", "不透明度", "朝向", "子弹速度", 
			"子弹速度方向", "子弹加速度", "子弹加速度方向", 
			"横比", "纵比", "雾化效果", "消除效果", 
			"高光效果", "拖影效果", "出屏即消", "无敌状态")
	#特殊的结果
	superresname = {"恢复到初始状态":-2, "额外发射":-3}
	emconmap = {}
	for k in emconname:
		emconmap[k] = emconname.index(k)
	emresmap = {}
	for k in emresname:
		emresmap[k] = emresname.index(k)
	# 发射器子弹的事件编号
	buconname = ("当前帧", "X坐标", "Y坐标")
	buresname = ("生命", "类型", "宽比", "高比", "R", "G", "B", 
			"不透明度", "朝向", "子弹速度", "子弹速度方向", 
			"子弹加速度", "子弹加速度方向", "横比", "纵比", 
			"雾化效果", "消除效果", "高光效果", "拖影效果",
			"出屏即消", "无敌状态")
	buconmap = {}
	for k in buconname:
		buconmap[k] = buconname.index(k)
	buresmap = {}
	for k in buresname:
		buresmap[k] = buresname.index(k)

	def __init__(self, oridata):
		self.action = [] #事件
		self.bullet = {'action':[]} #子弹事件
		super(Emitter, self).__init__(EMITTER, oridata)

	def analyze(self, data):
		#data[0] , data[1]发射器ID, 层ID(忽略)
		#data[2],绑定了吗，　data[3],绑定的ID (忽略) ,data[4] 相对方向不使用, data[5]抛弃使用
		self.pos = (float(data[6]), float(data[7])) #位置坐标
		self.frame = (int(data[8]), int(data[8]) + int(data[9])) #播放的起始结束帧存两个uint32
		self.emitpos = (float(data[10]), float(data[11]), float(data[53]), float(data[54])) #发射坐标存两个float, 和其随机量
		#发射器半径和旋转角度,及其它们的随机量float
		self.emitedge = (float(data[12]), float(data[13]), float(data[55]), float(data[56])) 
		self.nmuzzle = (int(data[15]), int(data[57]))	#炮口数量uint16
		self.freq = (int(data[16]), int(data[58])) # 发射周期及其随机量uint32
		self.angle = (float(data[17]), float(data[59])) #发射起始方向旋转角度以及角度的随机量float
		self.emitrange = (int(data[19]), int(data[60])) #射击范围及其随机量，存int16
		self.v = (float(data[20]), float(data[21]), float(data[61]), float(data[62])) #速度和速度方向及随机量
		self.va = (float(data[23]), float(data[24]), float(data[63]), float(data[64])) #加速度和加速度方向及随机量
		#73深度绑定(忽略)
		####### 以下是子弹信息 #######
		#data[38]  是子弹的初始速度方向，不使用
		#是否受到遮罩,反弹板和力场的控制(忽略)
		#self.bullet['factor'] = (bool_str(data[70]), bool_str(data[71]), bool_str(data[72]))
		self.bullet['life'] = int(data[26]) #子弹生命 uint32
		self.bullet['ID'] = int(data[27]) #子弹类型 int32
		self.bullet['WHscale'] = (float(data[28]), float(data[29])) #宽高比(y方向和x方向的缩放倍率)
		self.bullet['color'] = (int(data[30]), int(data[31]),int(data[32])) #RGB的颜色叠加值，存3个uint8_t
		self.bullet['alpha'] = int(data[33]) * 255 / 100 #透明度 uint8_t
		self.bullet['sangle'] = (int(data[34]), int(data[65])) #朝向及随机量 int16_t
		#print "sangle is %d"%self.bullet['sangle']
		self.bullet['v'] = (float(data[37]), float(data[66])) #子弹的初速度及随机量 float
		#子弹的加速度和加速度方向及其随机量
		self.bullet['va'] = (float(data[40]), float(data[41]), float(data[68]), float(data[69]))
		self.bullet['xyvrate'] = (float(data[43]), float(data[44])) #x,y方向的加速度的倍率
		#七个个bool(雾化，消弹， 发射高亮，拖影，出屏消亡，无敌,朝向是否使用发射器发出的起始速度方向)
		self.bullet['effect'] = (bool_str(data[45]), bool_str(data[46]),bool_str(data[47]), \
				bool_str(data[48]), bool_str(data[49]), bool_str(data[50]), bool_str(data[36]))
		#发射器事件处理
		self.action = emLaMaActionDivider(data[51], Emitter.emconmap, Emitter.emresmap)
		for k in self.action:
			#k是事件组
			for ack in k['ac']:
				#ack是每一个事件
				if type(ack['result']) == str:
					ack['result'] = {'which':Emitter.superresname[ack['result']]}
		#子弹事件处理
		self.bullet['action'] = emLaMaActionDivider(data[52], Emitter.buconmap, Emitter.buresmap)

	def data(self):
		'''返回格式化的数据 '''
		#2I起始结束帧, 4f发射半径和旋转角度, 2I发射周期 , 8f速度和加速度,
		#2f发射起始方向, 2h射击范围,2H炮口数量
		ret = struct.pack("%c2I4f2I8f2f2h2H" % TARGET_BYTE_ORDER, self.frame[0], self.frame[1], 
				self.emitedge[0], self.emitedge[1], self.emitedge[2],self.emitedge[3], 
				self.freq[0], self.freq[1], self.v[0], self.v[1], self.v[2], self.v[3], 
				self.va[0], self.va[1], self.va[2], self.va[3], self.angle[0], self.angle[1],
				self.emitrange[0], self.emitrange[1], self.nmuzzle[0], self.nmuzzle[1])
		#发射坐标2i,发射器事件组个数I
		ret += struct.pack("%c4fI" % TARGET_BYTE_ORDER, self.emitpos[0], self.emitpos[1],
				self.emitpos[2], self.emitpos[3], len(self.action))
	
		#发射器事件	
		ret += action2data(self.action)
		#iI子弹类型和生命, 2f速度和速度随机量,4f加速度和加速度随机量, 2f X:Y方向的缩放
		bu = self.bullet
		ret += struct.pack("%ciI2f4f2f" % TARGET_BYTE_ORDER,  bu['ID'], bu['life'], bu['v'][0], bu['v'][1],
				bu['va'][0],bu['va'][1],bu['va'][2],bu['va'][3],
				bu['WHscale'][1],bu['WHscale'][0])
		#计算特效
		effect = 0 
		tmp = 0
		for k in bu['effect']:
			if k:
				effect = effect | (1<<tmp)
			tmp += 1
		#子弹4B颜色, 2f加速度缩放, i特效, I子弹事件组个数
		ret += struct.pack("%c4B2fiI" % TARGET_BYTE_ORDER, bu['color'][0],bu['color'][1],bu['color'][2],
				bu['alpha'], bu['xyvrate'][0],bu['xyvrate'][1], effect, len(bu['action']))
		#print bu['action']
		#子弹事件
		ret += action2data(bu['action'])
		return ret
	
class Laser(CSObj):

	"""发射器的类"""
	# 发射器的事件编号
	emconname = ("当前帧",  "半径", "半径方向",
			"条数", "周期", "角度", "范围", "宽比", 
			"长度", "不透明度")
	# 变化的结果
	emresname = ( "半径", "半径方向", "条数", "周期",
			"角度", "范围", "速度", "速度方向", "加速度",
			"加速度方向", "生命", "类型", "宽比", "长度", 
			"不透明度", "子弹速度", "子弹速度方向", "子弹加速度", "子弹加速度方向", 
			"横比", "纵比",  "高光效果", "出屏即消", "无敌状态")
	#特殊的结果
	superresname = {"恢复到初始状态":-2, "额外发射":-3}
	emconmap = {}
	for k in emconname:
		emconmap[k] = emconname.index(k)
	emresmap = {}
	for k in emresname:
		emresmap[k] = emresname.index(k)
	# 发射器子弹的事件编号
	buconname = ("当前帧", "X坐标", "Y坐标")
	buresname = ("生命", "类型", "宽比", "高比", "R", "G", "B", 
			"不透明度", "朝向", "子弹速度", "子弹速度方向", 
			"子弹加速度", "子弹加速度方向", "横比", "纵比", 
			"雾化效果", "消除效果", "高光效果", "拖影效果",
			"出屏即消", "无敌状态")
	buconmap = {}
	for k in buconname:
		buconmap[k] = buconname.index(k)
	buresmap = {}
	for k in buresname:
		buresmap[k] = buresname.index(k)
	def __init__(self, oridata):
		self.action = [] #事件
		self.bullet = {'action':[]} #子弹事件
		super(Laser, self).__init__(LASER, oridata)

	def analyze(self, data):
		#data[0] , data[1]发射器ID, 层ID(忽略)
		#data[2],绑定了吗，　data[3],绑定的ID (忽略) ,data[4] 相对方向不使用, data[5]抛弃使用
		self.pos = (float(data[6]), float(data[7])) #位置坐标
		self.frame = (int(data[8]), int(data[8]) + int(data[9])) #播放的起始结束帧存两个uint32
		self.emitedge = (float(data[10]), float(data[11]), float(data[44]), float(data[45])) 
		self.nmuzzle = (int(data[13]), int(data[46]))	#炮口数量uint16
		self.freq = (int(data[14]), int(data[47])) # 发射周期及其随机量uint32
		self.angle = (float(data[15]), float(data[48])) #发射起始方向旋转角度以及角度的随机量float
		self.emitrange = (int(data[17]), int(data[49]))#射击范围及其随机量，存int16
		self.v = (float(data[18]), float(data[19]), float(data[50]), float(data[51])) #速度和速度方向及随机量
		self.va = (float(data[21]), float(data[22]), float(data[52]), float(data[53])) #加速度和加速度方向及随机量
		#73深度绑定(忽略)
		####### 以下是子弹信息 #######
		#data[38]  是子弹的初始速度方向，不使用
		#是否受到遮罩,反弹板和力场的控制(忽略)
		#self.bullet['factor'] = (bool_str(data[70]), bool_str(data[71]), bool_str(data[72]))
		self.bullet['life'] = int(data[24])  #子弹生命 uint32
		self.bullet['ID'] = int(data[25])  #子弹类型 int32
		self.bullet['WHscale'] = (float(data[26]), float(data[27]))  #宽高比(y方向和x方向的缩放倍率)
		self.bullet['alpha'] = int(data[28]) * 255 / 100 #透明度 uint8_t
		self.bullet['startX'] = (bool_str(data[29])) #开启射线激光
		self.bullet['v'] = (float(data[30]), float(data[54]))#子弹的初速度及随机量 float
		#子弹的加速度和加速度方向及其随机量	
		self.bullet['va'] = (float(data[33]), float(data[34]), float(data[56]), float(data[57]))
		self.bullet['xyvrate'] = (float(data[36]), float(data[37])) #x,y鏂瑰悜鐨勫姞閫熷害鐨勫€嶇巼
		
		self.bullet['effect'] = (bool_str(data[38]), bool_str(data[39]),bool_str(data[40]))
		
		
		#发射器事件处理	
		self.action = emLaMaActionDivider(data[42], Laser.emconmap, Laser.emresmap)
		#子弹事件处理
		self.bullet['action'] = emLaMaActionDivider(data[43], Laser.buconmap, Laser.buresmap)

	def data(self):
		'''返回格式化的数据 '''
		#2I起始结束帧, 4f发射半径和旋转角度, 2I发射周期 , 8f速度和加速度,
		#2f发射起始方向, 2h射击范围,2H炮口数量
		ret = struct.pack("%c2I4f2I8f2f2h2HI" % TARGET_BYTE_ORDER, self.frame[0], self.frame[1], 
				self.emitedge[0], self.emitedge[1], self.emitedge[2],self.emitedge[3], 
				self.freq[0], self.freq[1], self.v[0], self.v[1], self.v[2], self.v[3], 
				self.va[0], self.va[1], self.va[2], self.va[3], self.angle[0], self.angle[1],
				self.emitrange[0], self.emitrange[1], self.nmuzzle[0], self.nmuzzle[1],len(self.action))
		#发射器事件	

		ret += action2data(self.action)
		#iI子弹类型和生命, 2f速度和速度随机量,4f加速度和加速度随机量, 2f X:Y方向的缩放
		bu = self.bullet
		ret += struct.pack("%ciI2f4f2f" % TARGET_BYTE_ORDER,  bu['ID'], bu['life'], bu['v'][0], bu['v'][1],
				bu['va'][0],bu['va'][1],bu['va'][2],bu['va'][3],
				bu['WHscale'][1],bu['WHscale'][0])
		#计算特效
		effect = 0 
		tmp = 0
		for k in bu['effect']:
			if k:
				effect = effect | (1<<tmp)
			tmp += 1
	
		ret += struct.pack("%c4B2f2iI" % TARGET_BYTE_ORDER,255,255,255,
				bu['alpha'], bu['xyvrate'][0],bu['xyvrate'][1], effect, bu['startX'],len(bu['action']))
		ret += action2data(bu['action'])
		return ret

class Layer(object):
	"""格式化数据的类"""
	def __init__(self):
		super(Layer, self).__init__()
		self.objarr = []	#元素对象
		for k in range(0, INTER_OBJ_NUM):
			self.objarr.append([])

	def addObj(self, obj):
		#判定元素类型
		self.objarr[obj.t].append(obj.data())

	def objNum(self):
		ret = 0
		for k in self.objarr:
			ret += len(k)
		return ret

	def formatData(self):
		"""返回格式化的数据"""
		#起始结束帧，每种元素的数量
		ret = ''
		for k in self.objarr:
			ret += struct.pack("%cI" % TARGET_BYTE_ORDER, len(k))
		#发射器和激光的数据长度
		for k in self.objarr:
			for p in k:
				#加的20是下面的名字长度16 + 一个整形类型的4
				ret += struct.pack("%cI" % TARGET_BYTE_ORDER, len(p) + 20)
		#元素的类型，元素的名称, 元素的值
		objname = ('em', 'la')
		t = 0
		for k in self.objarr:
			tmp = 0
			for p in k:
				#NOTE:元素的名称由'类型名#编号'组成, 不能超过16个字符长度
				name = '%s#%d' % (objname[t], tmp)
				if len(name) > 15:
					print '错误: 需要缩减文件名长度'
					exit()
				while len(name) < 16:
					name += chr(0)
				ret += struct.pack("%ci16s" % TARGET_BYTE_ORDER, t, name)
				ret += p
				tmp += 1
			t += 1
		return ret

class CSB_Data(object):
	"""格式化数据的类"""
	def __init__(self):
		super(CSB_Data, self).__init__()
		self.version = 0x01	#数据版本
		self.layer = []		#层对象
		self.totalframe = 0	#总帧数

	def addLayer(self, player):
		if player and (player.objNum() > 0):
			self.layer.append(player)

	def formatData(self):
		"""返回格式化的数据"""
		#文件头: 版本号，总数据长度，层数
		ret = ''
		for k in self.layer:
			ret += k.formatData()
		return struct.pack("%c3I" % TARGET_BYTE_ORDER, self.version, len(self.layer), self.totalframe) + ret

############| 分析函数 |############

def readLayer(ldata, csbdata, CSObjArr):
	'''读取一层的数据ldata，分析它，然后写入csbdata
	ldata 是一个OBJ_NUM长度的数组，每个数组里面又是一个数组。
	每个元素是一个obj
	'''
	# 创建一个层
	pl = Layer()
	#依次解析各种结构
	idx = 0
	for k in ldata:
		for lk in k:
			pl.addObj(CSObjArr[idx](lk))
		idx += 1
	#添加到解析层内
	csbdata.addLayer(pl)


def showhelp(name):
	l =  (60 - len(name)) / 2
	#TODO: 添加j表示json文件
	print '#' * l + '|', name, '|' + '#' * l
	print '用法:'
	print '	python %s [-b b|l] [-R] <弹幕编辑器出来的mbg文件列表|递归查找mbg文件的路径>' % name 
	print '	-b	指定使用何种字节序进行文件的数据排布。'
	print '		b大端字节序，l小端字节序。默认使用小端。'
	print '	-R	指定递归查找mbg文件的路径。此参数就忽略文件列表。'
	print '要求:'
	print '	弹幕文件版本需是CrazyStorm 1.01或其以上'
	print '#' * 64

############| 入口函数 |############
if __name__ == '__main__':
	from sys import argv
	#获取字节序
	try:
		bidx = argv.index('-b')
		try:
			o = argv[bidx + 1]	
			if 'b' == o:
				TARGET_BYTE_ORDER = '>'
			elif 'l' == o:
				#默认就是小端字节序
				pass
			else:
				showhelp(argv[0])
				exit()
		except IndexError:
			showhelp(argv[0])
			exit()
		#剔除两个字节序控制位
		bidx = 3
	except ValueError:
		bidx = 1

	try:
		ridx = argv.index('-R')
		ridx += 1
	except ValueError:
		ridx = -1

	if ((ridx < 0) and len(argv[bidx:]) < 1) or (len(argv[ridx:]) < 1):
		showhelp(argv[0])
		exit()

	if 'j' == TARGET_BYTE_ORDER:
		print '>>>>>>>>>>>>> Use format Json print <<<<<<<<<<<<<'
	else:
		print '>>>>>>>>>>>>> 22222222222%s <<<<<<<<<<<<<' % ('大' if '>' == TARGET_BYTE_ORDER else '小')
	#取得文件列表
	srcflist = []
	if ridx < 0:
		srcflist = argv[bidx:]
	else:
		import os
		for parent, dirnames, fnames in os.walk(argv[ridx]):
			for f in fnames:
				if 'mbg' == f[-3:]:
					srcflist.append(os.path.join(parent, f))
	for srcfile in srcflist:
		try:
			fp = open(srcfile, "rb")
			#输出文件的名字
			outfile = ''
			p = srcfile.rfind('.')
			if p < 0:
				outfile = srcfile
			else:
				outfile = srcfile[:p]
			outfile += '.csb'	
			#检测文件头版本
			fline = fp.readline()
			FILE_HEAD = "Crazy Storm Data 1.01"
			if FILE_HEAD != fline[:len(FILE_HEAD)]:
				print '%s 文件不是版本为1.01的Crazy Storm Data文件' % srcfile
				continue
			csbdata = CSB_Data()
			#读取中心坐标(忽略掉)
			fline = fp.readline()
                        if fline[0] != 'C':
                            for k in range(int(fline.split()[0]) + 1):
                                fp.readline()
			#读取总帧数(忽略掉)
			fline = fp.readline()
			csbdata.totalframe = int(fline.split(':')[1])
			#检测是否是可读的层(一共4层，不为empyt就可读)
			CSObjArr = (Emitter, Laser)
			for k in xrange(0, 4):
				fline = fp.readline().split(':')[1]
				if 'empty' == fline[:len('empty')]:
					continue
				fdata = fline.split(',')
				#依次是:图层名, 起始帧，结束帧，发射器数目，激光数目，遮罩数目，反弹板数目，力场数目
				objarr = []
				for key in xrange(0, INTER_OBJ_NUM):
					objarr.append([])
				for key in xrange(3, 3 + INTER_OBJ_NUM):
					idx = key - 3
					for j in xrange(0, int(fdata[key])):
						objarr[idx].append(fp.readline())
				#抛弃掉遮罩等力场数据
				for key in xrange(3 + INTER_OBJ_NUM, 3 + INTER_OBJ_LIMIT):
					for j in xrange(0, int(fdata[key])):
						fp.readline()
				readLayer(objarr, csbdata, CSObjArr)
			fp.close()
		except IOError:
			print '读取文件 %s 时出现IO错误' % srcfile
			continue

		try:
			#开始写入文件
			fp = open(outfile, "wb")
			fp.write(csbdata.formatData())
			fp.close()
			print '%s ----> %s' % (srcfile, outfile)
		except IOError:
			print '写入文件时出现IO错误'
